<?php
/**
 * Short Description  
 *
 * Long Description 
 *
 * @category   
 * @package    
 * @subpackage 
 * @copyright 
 * @author     Sandeep Manne<sandeep.manne@costrategix.com>
 */

/**
 * http://wiki.costrategix.net/display/COSPROCESS/Video+Editing+with+ffmpeg+and+MEncoder
 */

require_once "Core/Video/Adapter/Abstract.php";
require_once "Core/Video/Exception.php";
require_once "Core/System.php";
require_once "Zend/Validate/File/MimeType.php";

class Core_Video_Adapter_Mencoder extends Core_Video_Adapter_Abstract
{
	private $_outputFullPath = null;
	private $_videoFilters   = array();
	protected $_requiredExtensions = array("ffmpeg");
	private $_ffmpegMovie = null;
	
	private $_waterMarkCommand = "";
	
	public function __construct($fileName = null)
	{
		$this->checkDependencies();
		$this->open($fileName);
	}

	public function open($fileName)
	{
		$this->_fileName = $fileName;
		$this->_ffmpegMovie = new ffmpeg_movie($this->_fileName);
		$this->_validateVideoFile();
	}

    public function save($destination = null, $newFileName = null)
    {
    	if (is_dir($destination)) {
    		$this->_outputFullPath = $destination. '/' . $newFileName;
    	} else {
    		throw new Core_Video_Exception("Destination is not a valid directory");
    	}
    	
    	$system = Core_System::getInstance();
    	
    	if (count($this->_videoFilters) != 0)
    	foreach ($this->_videoFilters as $videoFilter) { 
    		
    		if ($videoFilter === " bmovl=0:0:logo.fifo ") {
    			var_dump($system->run($this->_waterMarkCommand));
    		}
	    	$command  = $system->getCommandPath("mencoder");
	    	$command .= " -vf " . $videoFilter;
			$command .= " -o " . $destination . "/" . $newFileName;
			$command .= " -oac copy -ovc lavc ";
			$command .= $this->_fileName;
			
			var_dump($system->run($command));
    	}
    }

    
    /**
     * mencoder -vf scale=w:h -o output.flv -oac copy -ovc lavc input.mpg
     * 
     * @param unknown_type $width
     * @param unknown_type $height
     */
    public function resize($width = null, $height = null)
    {
    	$this->_videoFilters[] = " scale=" . $width . ":" . $height . " ";
    	return $this;
    }

    /**
     * http://www.hanselman.com/blog/HowToRotateAnAVIOrMPEGFileTakenInPortrait.aspx
     * mencoder -vf rotate=1 -o output.flv -oac copy -ovc lavc input.mpg
     * 
     * @param unknown_type $angle
     */
    public function rotate($angle)
    {
    	$this->_videoFilters[] = " rotate=" . ($angle/90) . " ";
    	return $this;
    }
	
    /**
     * mencoder -vf crop=t:l:r:b -o output.flv -oac copy -ovc lavc input.mpg
     * 
     * @param unknown_type $top
     * @param unknown_type $left
     * @param unknown_type $right
     * @param unknown_type $bottom
     */
    public function crop($top=0, $left=0, $right=0, $bottom=0)
    {
    	$this->_videoFilters[] = " crop=" . $top . ":" . $left . ":" .
    							$right  . ":"  . $bottom . " ";
    	return $this;
    }

    /**
     * http://linux.goeszen.com/watermark-video-with-ffmpeg.html
     * 
     * 
     * @param string $watermarkImage - A RGB format image
     * @param int    $positionX      - X Position
     * @param int    $positionY      - Y Position
     */
    public function watermark($watermarkImage, $ImageWidth, $ImageHeight, $positionX=0, $positionY=0)
    {
    	$validator = new Zend_Validate_File_MimeType("text/plain");
    	if (!$validator->isValid($watermarkImage)) {
    		throw new Core_Video_Exception("Water mark Image must of type rgba " .mime_content_type($watermarkImage));
    	}
   		$this->_waterMarkCommand = "( echo \"RGBA32 "
   								    . $ImageWidth . " " . $ImageHeight . " " . $positionX . " " . $positionY .
   								    " 0 1\"; cat  " . $watermarkImage . " ) > /home/sandeep/pdtworkspace/base/public/logo.fifo &";

  		$this->_videoFilters[] = " bmovl=0:0:logo.fifo ";
  		return $this;
    }

    public function checkDependencies()
    {
    	$system = Core_System::getInstance();
    	if (!$system->isCommandExist("ffmpeg") 
    		|| !$system->isCommandExist("mencoder")) {
    			throw new Core_Video_Exception("ffmpeg and mencoder is required");
    	}
    	$system->checkPhpExtensions($this->_requiredExtensions);
    }
    
    public function getOriginalWidth()
    {
    	return $this->_ffmpegMovie->getFrameWidth();
    }
    
    public function getOriginalHeight()
    {
    	return $this->_ffmpegMovie->getFrameHeight();
    }
    
    public function keepAspectRatio($value = null)
    {
    	
    }
    
    public function getDuration()
    {
    	return $this->_ffmpegMovie->getDuration();
    }
    
    public function getBitRate()
    {
    	return $this->_ffmpegMovie->getBitRate();
    }
    
    public function getMetaData()
    {
    	return array ("Title"     => $this->_ffmpegMovie->getTitle(),
    				  "Artist"    => $this->_ffmpegMovie->getAuthor(), 
    				  "Copyright" => $this->_ffmpegMovie->getCopyright(),
    				  "Year"      => $this->_ffmpegMovie->getYear(),
    				  "Duration"  => $this->getDuration(),
    				  "Bitrate"   => $this->getBitRate(),
    				  "Dimensions"=> $this->getOriginalWidth() . "x" . $this->getOriginalHeight()
    				 );
    }
    
    public function getSupportedTypes(){}
    
    public function getThumbnail($time, $size, $outputFileName)
    {
    	$system = Core_System::getInstance();
    	
    	return $system->run(
    				 $system->getCommandPath("ffmpeg") .              //ffmpeg command path  
    				 " -i " . $this->_fileName . " -ss " .            //Video File name
    				 $this->_getFfmpegTime($time) .                   //Thumbnail Position
    				 " -vframes 1 -s " . $size . " -r 1 -f png -y ". //Thumbnail Size
    				 $outputFileName								  //Output file name
    				);
    }
    
    public function quality($value = null){}
    
    private function _validateVideoFile()
    {
    	if (!file_exists($this->_fileName) 
    		|| filesize($this->_fileName) < 10000 
    		|| filesize($this->_fileName) == 0) { //Video file with < 10KB
    		throw new Core_Video_Exception("Invalid file, better to delete");
    	}
    	
    	$validator = new Zend_Validate_File_MimeType("video");
    	if (!$validator->isValid($this->_fileName)) {
    		throw new Core_Video_Exception("Invalid file type");
    	}
    }
    
    private function _getFfmpegTime($time)
    {
    	$ffmpeg_hours = floor($time / 3600);
    	$ffmpeg_mins = floor($time % 3600 / 60);
    	$ffmpeg_secs = floor($time % 60);
    	$ffmpeg_time = sprintf("%02d:%02d:%02d",$ffmpeg_hours,$ffmpeg_mins,$ffmpeg_secs);
    	return $ffmpeg_time;
    }
}